library ieee;
use ieee.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;

package typeDefinitions is
  type operation is (o_addu, o_addiu, o_and, o_andi, o_jr, o_nor, o_or, o_slt, o_sltu, o_sll, o_srl, o_subu, o_xor, o_beq, o_bne, o_lui, o_lw, o_ori, o_slti, o_sltiu, o_sw, o_ll, o_sc, o_xori, o_j, o_jal, o_halt, o_nop);

  type pcSel is (pc_add4, pc_ext, pc_adj, pc_curr, pc_busA);

  type regDestSel is (reg_rd, reg_rt, reg_31);

  type aluSrcSel is (alu_busB, alu_imm, alu_shft);

  type aluOp is (op_add, op_sub, op_sll, op_srl, op_and, op_or, op_xor, op_nor, op_slt);

  type stageHoldSignals is record
    pc    : std_logic;
    fetch : std_logic;
    id    : std_logic;
    exec  : std_logic;
    mem   : std_logic;
    wb    : std_logic;
  end record;

  type stageInvalidateSignals is record
    fetch : std_logic;
    id    : std_logic;
    exec  : std_logic;
    mem   : std_logic;
    wb    : std_logic;
  end record;

  type interStage32 is record
    fetch : std_logic_vector(31 downto 0);
    id    : std_logic_vector(31 downto 0);
    exec  : std_logic_vector(31 downto 0);
    mem   : std_logic_vector(31 downto 0);
  end record;

  type interStage5 is record
    fetch : std_logic_vector(4 downto 0);
    id    : std_logic_vector(4 downto 0);
    exec  : std_logic_vector(4 downto 0);
    mem   : std_logic_vector(4 downto 0);
  end record;

  type interStageOperation is record
    fetch  : std_logic_vector(31 downto 0);
    decode : operation;
    id     : operation;
    exec   : operation;
    mem    : operation;
  end record;

  type fetchUnique is record
    busA     : std_logic_vector(31 downto 0);
    jumpAddr : std_logic_vector(25 downto 0);
    pcOld    : std_logic_vector(31 downto 0);
    pcOld_in : std_logic_vector(31 downto 0);
    halt     : std_logic;
    sel      : pcSel;
  end record;

  type idUnique is record
    busA  : std_logic_vector(31 downto 0);
    busB  : std_logic_vector(31 downto 0);
    rdat1 : std_logic_vector(31 downto 0);

    wDest : std_logic_vector(4 downto 0);
    wEn   : std_logic;
    wData : std_logic_vector(31 downto 0);

    upper     : std_logic_vector(31 downto 0);
    immediate : std_logic_vector(31 downto 0);  --extended
    shftamnt  : std_logic_vector(4 downto 0);


    rs : std_logic_vector(4 downto 0);
    rt : std_logic_vector(4 downto 0);
  end record;

  type execUnique is record
    aluResult : std_logic_vector(31 downto 0);
    busB      : std_logic_vector(31 downto 0);
    upper     : std_logic_vector(31 downto 0);

    rs : std_logic_vector(31 downto 0);
    rt : std_logic_vector(31 downto 0);
  end record;

  type memUnique is record
    aluResult : std_logic_vector(31 downto 0);
    dataMem   : std_logic_vector(31 downto 0);
    upper     : std_logic_vector(31 downto 0);
    rt        : std_logic_vector(4 downto 0);
  end record;

  type memSignal is record
    addr  : std_logic_vector(15 downto 0);
    wData : std_logic_vector(31 downto 0);
    rData : std_logic_vector(31 downto 0);
    wEN   : std_logic;
    rEN   : std_logic;
    state : std_logic_vector(1 downto 0);
  end record;

  type cacheSignal is record
    addr  : std_logic_vector(31 downto 0);
    wData : std_logic_vector(31 downto 0);
    rData : std_logic_vector(31 downto 0);
    wEN   : std_logic;
    rEN   : std_logic;
    stall : std_logic;
  end record;

  type idForwardIn is record
    busA : std_logic_vector(31 downto 0);
    busB : std_logic_vector(31 downto 0);
    selA : std_logic;
    selB : std_logic;
  end record;

  type execForwardIn is record
    busA : std_logic_vector(31 downto 0);
    busB : std_logic_vector(31 downto 0);
    selA : std_logic;
    selB : std_logic;
  end record;

  type memForwardIn is record
    busB : std_logic_vector(31 downto 0);
    selB : std_logic;
  end record;

  type forwardSignalsIn is record
    id   : idForwardIn;
    exec : execForwardIn;
    mem  : memForwardIn;
  end record;

  type idForwardOut is record
    nPCSel : pcSel;
    rs     : std_logic_vector(4 downto 0);
    rt     : std_logic_vector(4 downto 0);
  end record;

  type execForwardOut is record
    rs          : std_logic_vector(4 downto 0);
    rt          : std_logic_vector(4 downto 0);
    destination : std_logic_vector(4 downto 0);
  end record;

  type memForwardOut is record
    aluResult   : std_logic_vector(31 downto 0);
    destination : std_logic_vector(4 downto 0);
    rt          : std_logic_vector(4 downto 0);
    
  end record;

  type wbForwardOut is record
    writeData   : std_logic_vector(31 downto 0);
    destination : std_logic_vector(4 downto 0);
  end record;

  type wb2ForwardOut is record
    writeData   : std_logic_vector(31 downto 0);
    destination : std_logic_vector(4 downto 0);
  end record;


  type forwardSignalsOut is record
    id   : idForwardOut;
    exec : execForwardOut;
    mem  : memForwardOut;
    wb   : wbForwardOut;
    wb2  : wb2ForwardOut;
  end record;

  type forwardSignals is record
    ins  : forwardSignalsIn;
    outs : forwardSignalsOut;
  end record;

  type icacheCntrl is record
    hit   : std_logic;
    tag   : std_logic_vector(25 downto 0);
    index : std_logic_vector(3 downto 0);
    rData : std_logic_vector(31 downto 0);
    wEn   : std_logic;
  end record;

  type dcacheCntrl is record
    hit     : std_logic;
    tag     : std_logic_vector(25 downto 0);
    tag_out : std_logic_vector(25 downto 0);
    index   : std_logic_vector(3 downto 0);
    rData   : std_logic_vector(31 downto 0);
    wData   : std_logic_vector(31 downto 0);
    wEn     : std_logic;
  end record;

  type dcacheSetCntrl is record
    clk      :  std_logic;
    nrst     :  std_logic;
    tag_in   :  std_logic_vector(24 downto 0);
    data_in  :  std_logic_vector(63 downto 0);
    index_in :  std_logic_vector(3 downto 0);

    recent_in :  std_logic;
    dirty_in  :  std_logic;

    recent_wen :  std_logic;
    data_wen   :  std_logic;

    data_out :  std_logic_vector(63 downto 0);
    tag_out  :  std_logic_vector(24 downto 0);
    hit      :  std_logic;
    dirty    :  std_logic;
    recent   :  std_logic;
  end record;

end typeDefinitions;
